{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "PREREQUISITES\n",
    "\n",
    "This guide assumes familiarity with the following concepts:\n",
    "\n",
    "- [Callbacks](https://python.langchain.com/docs/concepts/callbacks/)\n",
    "- [Custom callback handlers](https://python.langchain.com/docs/how_to/custom_callbacks/)\n",
    "\n",
    "\n",
    "在大多数情况下，在运行对象时传入处理程序更为有利。当我们通过回调关键字参数在运行时传递回调处理程序时，这些回调将由所有参与执行的嵌套对象发出。例如，当处理程序传递给代理时，它将用于与代理相关的所有回调以及参与代理执行的所有对象，在这种情况下，工具和 LLM。"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "7624bd69665bda1e"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Error in LoggingHandler.on_chain_start callback: AttributeError(\"'NoneType' object has no attribute 'get'\")\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Chain ChatPromptTemplate started\n",
      "Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?', additional_kwargs={}, response_metadata={})]\n",
      "Chat model started\n",
      "Chat model ended, response: generations=[[ChatGeneration(text='1 + 2 equals 3.', generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content='1 + 2 equals 3.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 26, 'total_tokens': 34, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen-max', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-0f7be862-6018-4b14-80dc-3e568bbdc515-0', usage_metadata={'input_tokens': 26, 'output_tokens': 8, 'total_tokens': 34, 'input_token_details': {}, 'output_token_details': {}}))]] llm_output={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 26, 'total_tokens': 34, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen-max', 'system_fingerprint': None} run=None type='LLMResult'\n",
      "Chain ended, outputs: content='1 + 2 equals 3.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 26, 'total_tokens': 34, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen-max', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-0f7be862-6018-4b14-80dc-3e568bbdc515-0' usage_metadata={'input_tokens': 26, 'output_tokens': 8, 'total_tokens': 34, 'input_token_details': {}, 'output_token_details': {}}\n"
     ]
    },
    {
     "data": {
      "text/plain": "AIMessage(content='1 + 2 equals 3.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 26, 'total_tokens': 34, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'qwen-max', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-0f7be862-6018-4b14-80dc-3e568bbdc515-0', usage_metadata={'input_tokens': 26, 'output_tokens': 8, 'total_tokens': 34, 'input_token_details': {}, 'output_token_details': {}})"
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "from typing import Any, Dict, List\n",
    "\n",
    "from dotenv import load_dotenv\n",
    "from langchain_core.callbacks import BaseCallbackHandler\n",
    "from langchain_core.messages import BaseMessage\n",
    "from langchain_core.outputs import LLMResult\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "load_dotenv()\n",
    "llm = ChatOpenAI(\n",
    "    # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "    openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "    openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "    model_name=\"qwen-max\",\n",
    "    max_retries=0,\n",
    ")\n",
    "\n",
    "class LoggingHandler(BaseCallbackHandler):\n",
    "    def on_chat_model_start(\n",
    "        self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs\n",
    "    ) -> None:\n",
    "        print(\"Chat model started\")\n",
    "\n",
    "    def on_llm_end(self, response: LLMResult, **kwargs) -> None:\n",
    "        print(f\"Chat model ended, response: {response}\")\n",
    "\n",
    "    def on_chain_start(\n",
    "        self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs\n",
    "    ) -> None:\n",
    "        print(f\"Chain {serialized.get('name')} started\")\n",
    "\n",
    "    def on_chain_end(self, outputs: Dict[str, Any], **kwargs) -> None:\n",
    "        print(f\"Chain ended, outputs: {outputs}\")\n",
    "\n",
    "\n",
    "callbacks = [LoggingHandler()]\n",
    "\n",
    "prompt = ChatPromptTemplate.from_template(\"What is 1 + {number}?\")\n",
    "\n",
    "chain = prompt | llm\n",
    "\n",
    "chain.invoke({\"number\": \"2\"}, config={\"callbacks\": callbacks})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-10-31T06:03:39.803340Z",
     "start_time": "2024-10-31T06:03:36.854474Z"
    }
   },
   "id": "123b774005c6ab8d",
   "execution_count": 1
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
